﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ComponentModel;

using SPFarmModeler.Common;

namespace SPFarmModeler.Business
{
    [Serializable]
    public class Farm : INotifyPropertyChanged
    {
        #region Property Binding pour les Textbox
        // PropertyManagement avec binding objet <=> textbox
        private string name;
        public string Name                  // Farm name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
                NotifyPropertyChanged("Name");
            }
        }       

        private string description;
        public string Description
        {
            get
            {
                return description;
            }
            set
            {
                description = value;
                NotifyPropertyChanged("Description");
            }
        }        // Farm Description

        private string domainnb;
        public string DomainNB              // Domain NetBIOS name
        {
            get
            {
                return domainnb;
            }
            set
            {
                domainnb = value;
                NotifyPropertyChanged("DomainNB");
            }
        }

        private string domaindns;
        public string DomainDNS             // Domain DNS FQDN
        {
            get
            {
                return domaindns;
            }
            set
            {
                domaindns = value;
                NotifyPropertyChanged("DomainDNS");
            }
        }

        private int caport;                 // Central Admin TCP Port
        public int CentralAdminPort
        {
            get
            {
                return caport;
            }
            set
            {
                caport = value;
                NotifyPropertyChanged("CentralAdminPort");
            }
        }

        private string sqlconfigsvr;
        public string SQLConfigDbServer
        {
            get
            {
                return sqlconfigsvr;
            }
            set
            {
                sqlconfigsvr = value;
                NotifyPropertyChanged("SQLConfigDbServer");
            }
        }  // SQL server host of Farm configDB

        private string caconfdb;
        public string CentralAdminConfigDbName
        {
            get
            {
                return caconfdb;
            }
            set
            {
                caconfdb = value;
                NotifyPropertyChanged("CentralAdminConfigDbName");
            }
        }   // Farm configuration DB name

        private string caadmincontentdb;
        public string CentralAdminContentDbName
        {
            get
            {
                return caadmincontentdb;
            }
            set
            {
                caadmincontentdb = value;
                NotifyPropertyChanged("CentralAdminContentDbName");
            }
        }  // Central Admin content DB name
        
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
        
        public DateTime? LastSave { get; set; }
        
        // Detailed settings
        public FarmAuthentication Authentication { get; set; }
        public ServArch Archi { get; set; }
        public ServOS Os { get; set; }
        public ServSP Sp { get; set; }
        public ServED Ed { get; set; }

        public ServerList Servers;
        public List<WebApplication> WebApps;
        public List<ADUser> ServiceAccounts;

        /// <summary>
        /// Constructeur vide
        /// </summary>
        public Farm() 
        {
            Name = string.Empty;
            Description = string.Empty;
            DomainNB = string.Empty;
            DomainDNS = string.Empty;
            CentralAdminPort = 0;
            Authentication = FarmAuthentication.NTLM;
            Archi = ServArch.x86;
            Os = ServOS.Win2003R2;
            Sp = ServSP.RTM;
            Ed = ServED.Standard;
            SQLConfigDbServer = string.Empty;
            CentralAdminConfigDbName = string.Empty;
            CentralAdminContentDbName = string.Empty;
            Servers = new ServerList();
            WebApps = new List<WebApplication>();
            ServiceAccounts = new List<ADUser>();
        }

        /// <summary>
        /// Permet d'instancier un objet Farm à partir d'un fichier de configuration
        /// </summary>
        /// <param name="filePath">Chemin du fichier contenant la configuration à charger</param>
        /// <returns></returns>
        public static Farm Open(string filePath)
         {
            try
            {
                // Ouverture du fichier
                FileStream fs = File.Open(filePath, FileMode.Open);

                // Lecture du fichier
                string fileContent = string.Empty;
                byte[] b = new byte[1024];
                UTF8Encoding info = new UTF8Encoding(true);
                while (fs.Read(b, 0, b.Length) > 0)
                    fileContent += info.GetString(b);

                // Fermeture du fichier
                fs.Close();

                // Désérialisation de la configuration de la ferme
                return (Farm)Utilities.Deserialize(fileContent.ToString(), typeof(Farm));
            }
            catch (Exception ex)
            {
                throw new Exception("Farm.Open(...) : " + ex.Message);
            }
        }

        /// <summary>
        /// Permet de sauver une configuration de ferme dans un fichier
        /// </summary>
        /// <param name="fileName">Chemin du fichier dans lequel sauver la configuration de la ferme</param>
        public void Save(string fileName)
        {
            DateTime? currentLastSave = this.LastSave;
            try
            {
                // Validation des paramètres
                if ((fileName == null) || (fileName == string.Empty))
                    throw new Exception("Chemin non défini");

                // Si le fichier existe déjà, on le supprime...
                if (File.Exists(fileName))
                    File.Delete(fileName);

                // ... puis on le recrée
                FileStream fs = File.Create(fileName);

                // MAJ de la date de MAJ de la ferme
                this.LastSave = DateTime.Now;

                // Sérialisation de la configuration de la ferme
                byte[] info = new UTF8Encoding(true).GetBytes(Utilities.Serialize(this));

                // Ecriture dans le fichier
                fs.Write(info, 0, info.Length);

                // Fermeture du fichier
                fs.Close();
            }
            catch (Exception ex)
            {
                // On restore l'ancienne date de MAJ
                this.LastSave = currentLastSave;

                throw new Exception("Farm.Save(...) : " + ex.Message);
            }
        }
    }
}